package com.ruoyi.project.dzbqUtil.util;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.concurrent.atomic.AtomicBoolean;

import static com.ruoyi.project.dzbqUtil.util.SocketUtil.byteArrayToHexString;

public class ExecuteSocket {


    private Logger logger = LoggerFactory.getLogger(ExecuteSocket.class);

    /**
     * socket对象
     */
    private Socket socket;

    /**
     * 连接超时时间，默认是10s
     */
    private int connectTimeout = 10_000;

    /**
     * 接收数据超时时间，默认是10s
     */
    private int receiveTimeout = 10_000;

    /**
     * socket的地址
     */
    private InetSocketAddress socketAddress;

    /**
     * socket是否发生错误
     */
    private AtomicBoolean socketError;

    private String ip;

    public ExecuteSocket(String ip, int port) {

        this.socketError = new AtomicBoolean(false);//无并发，可用boolean代替
        this.socketAddress = new InetSocketAddress(ip, port);
        this.ip=ip;
        logger.info("------------链接开始！------------");
    }

//    public ExecuteSocket() {
//        this("127.0.0.1",3003);
//    }

    //连接校验
    private boolean checkConnected() {
        boolean b = !this.socketError.get() && this.socket != null && (socket.isConnected() && !socket.isClosed());
        return b;
    }
    //关闭连接
    public void close() {
        try {
            if (this.socket != null) {
                //System.out.println("stock"+socket);
                this.socket.close();
                this.socket = null;
            }
        } catch (IOException e) {
            //throw new SocketRuntimeException(e);
        }
    }

    //获取连接，异常直接抛出
    public Socket getAvailableSocket() throws Exception {


        // 已连接的直接返回socket
        if (this.checkConnected()) {
//            System.out.println("长连接是否支持？"+this.socket.getKeepAlive());
            return this.socket;
        }
        // 未连接，表示已断开，需要手动关闭socket，创建新的socket
        this.close();

        // 重新创建对象，并连接
        this.socket = new Socket();
        this.socket.setSoTimeout(1000);//6s
        this.socket.connect(this.socketAddress, this.connectTimeout);
        this.socketError.set(false);
        //this.doAfterConnected();
        logger.info("-------------ip:"+this.socketAddress+"重新连接--------------");
        return socket;

    }


    /*
     * 心跳
     * */
    public boolean writeHeart(String heartStr){
        Socket socket = null;
        try {
            socket = this.getAvailableSocket();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

        if(StringUtils.isBlank(heartStr)){
            return false;
        }

        try {
            OutputStream os = socket.getOutputStream();
            os.write(heartStr.getBytes());
            os.flush();
            return true;
        } catch (IOException e) {
            e.printStackTrace();
            logger.info("-------IP"+ip+"发送心跳异常---,["+e.getMessage()+"]---");
            return false;
        }

    }

    /*
     * 写入数据
     * */
    public boolean writeData(byte[] bytes){

        Socket socket = null;
        try {
            socket = this.getAvailableSocket();
        } catch (Exception e) {
            e.printStackTrace();
            logger.info("-------写入数据异常，原因获取连接失败，【"+e.getMessage()+"】------");
            return false;
        }
        try {
            OutputStream os = socket.getOutputStream();
            os.write(bytes);
            os.flush();
            return true;
        } catch (IOException e) {
            e.printStackTrace();
            logger.info("-------写入数据异常-,【"+e.getMessage()+"】-----");
            return false;
        }
    }

    /*
     * 读取
     * */
    public String readData() throws IOException {

        Socket socket;
        try {
            socket = this.getAvailableSocket();//连接超时，抛异常
        } catch (Exception e) {
            //e.printStackTrace();
            logger.info("-------IP"+ip+"获取连接失败---,【"+e.getMessage()+"】---");
            return "";
        }
        InputStream is = null;
        try {
            is = socket.getInputStream();
            int size = is.available();
            byte[] bytes = new byte[size];
            is.read(bytes);
            String content = byteArrayToHexString(bytes, size);
            return content;
        } catch (IOException e) {
            e.printStackTrace();
            is.close();
            return "";
        }
    }



}
